package org.jeecg.modules.business.job;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.business.repertory.entity.dto.CountQuantityDTO;
import org.jeecg.modules.business.repertory.mapper.WmsRepertoryMapper;
import org.jeecg.modules.basic.warehouse.entity.WmsBasicWarehouse;
import org.jeecg.modules.basic.warehouse.entity.WmsBasicWarehouseArea;
import org.jeecg.modules.basic.warehouse.entity.WmsBasicWarehouseAreaLocation;
import org.jeecg.modules.utils.dto.SmsDto;
import org.jeecg.modules.utils.service.IAlertService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.jeecg.modules.basic.warehouse.mapper.WmsBasicWarehouseMapper;
import org.jeecg.modules.basic.warehouse.mapper.WmsBasicWarehouseAreaMapper;
import org.jeecg.modules.basic.warehouse.mapper.WmsBasicWarehouseAreaLocationMapper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 仓库预警job
 *
 * @author zhoutong
 */
@Service
@Slf4j
public class AlartJob implements Job {

    @Resource
    private WmsBasicWarehouseMapper wmsBasicWarehouseMapper;
    @Resource
    private WmsBasicWarehouseAreaMapper wmsBasicWarehouseAreaMapper;
    @Resource
    private WmsBasicWarehouseAreaLocationMapper wmsBasicWarehouseAreaLocationMapper;
    @Resource
    private WmsRepertoryMapper wmsRepertoryMapper;
    @Autowired
    private IAlertService alertService;
    private AtomicInteger count = new AtomicInteger(1);

    private static final String MATERIALCODE = "materialCode";
    private static final String WAREHOUSENAME = "warehouseName";
    private static final String AREANAME = "areaName";
    private static final String LOCATIONNAME = "locationName";
    private static final String MATERIALQUANTITY = "materialQuantity";
    private static final String MAXQUANTITY = "maxQuantity";
    private static final String SAFEQUANTITY = "safeQuantity";
    private static final String MINQUANTITY = "minQuantity";
    private static final String WAREHOUSEID = "warehouseId";
    private static final String AREAID = "areaId";
    private static final String LOCATIONID = "locationId";

    @Override
    @Async
    public void execute(JobExecutionContext context) throws JobExecutionException {
        int i = 0;
        try {
            AtomicInteger integer = countWarehouse();
            i += integer.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        try {
            AtomicInteger integer = countArea();
            i += integer.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        try {
            AtomicInteger integer = countLocation();
            i += integer.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        log.info("共请求send方法[{}]次", i);
    }

    @Transactional(rollbackFor = Exception.class)
    public AtomicInteger countWarehouse() throws Exception {
        List<WmsBasicWarehouse> wmsBasicWarehouses = wmsBasicWarehouseMapper.selectList(new LambdaQueryWrapper<>());
        String maxTemplate = "warehouse-max";
        String safetyTemplate = "warehouse-safety";
        String minTemplate = "warehouse-min";
        AtomicInteger i = new AtomicInteger(0);
        List<CountQuantityDTO> warehouseQuantity = wmsRepertoryMapper.countWarehouse();
        for (CountQuantityDTO dto : warehouseQuantity) {
            SmsDto smsDto = new SmsDto();
            Map<String, Object> data = new HashMap<>();
            WmsBasicWarehouse warehouse = wmsBasicWarehouses.stream().filter(o -> o.getId().equals(dto.getWarehouseId())).findFirst().get();
            data.put(MATERIALCODE, dto.getMaterialCode());
            data.put(WAREHOUSENAME, warehouse.getName());
            data.put(MATERIALQUANTITY, dto.getQuantity());
            data.put(WAREHOUSEID, dto.getWarehouseId());
            if (ObjectUtil.isNotEmpty(warehouse.getMaxCapacity())) {
                //仓库存在数量大于等于最大容量
                if (dto.getQuantity().compareTo(warehouse.getMaxCapacity()) >= 0) {
                    //data.clear();
                    data.put(MAXQUANTITY, warehouse.getMaxCapacity());
                    send(smsDto, maxTemplate, data);
                    i.incrementAndGet();
                } else {
                    //data.clear();
                    data.put(MAXQUANTITY, warehouse.getMaxCapacity());
                    inactive(smsDto, maxTemplate, data);
                }
            }
            if (ObjectUtil.isNotEmpty(warehouse.getWarningCapacity())) {
                //仓库库存数量小于等于预警容量
                if (dto.getQuantity().compareTo(warehouse.getWarningCapacity()) <= 0) {
                    //data.clear();
                    data.put(SAFEQUANTITY, warehouse.getWarningCapacity());
                    send(smsDto, safetyTemplate, data);
                    i.incrementAndGet();
                } else {
                    //data.clear();
                    data.put(SAFEQUANTITY, warehouse.getWarningCapacity());
                    inactive(smsDto, safetyTemplate, data);
                }
            }
            //仓库库存数量小于等于最低容量
            if (dto.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
                //data.clear();
                data.put(MINQUANTITY, 0);
                send(smsDto, minTemplate, data);
                i.incrementAndGet();
            } else {
                //data.clear();
                data.put(MINQUANTITY, 0);
                inactive(smsDto, minTemplate, data);
            }
        }
        return i;
    }

    @Transactional(rollbackFor = Exception.class)
    public AtomicInteger countArea() throws Exception {
        List<WmsBasicWarehouseArea> wmsBasicWarehouseAreas = wmsBasicWarehouseAreaMapper.selectList(new LambdaQueryWrapper<>());
        String maxTemplate = "area-max";
        String safetyTemplate = "area-safety";
        String minTemplate = "area-min";
        AtomicInteger i = new AtomicInteger(0);
        List<CountQuantityDTO> areaQuantity = wmsRepertoryMapper.countArea();
        for (CountQuantityDTO dto : areaQuantity) {
            SmsDto smsDto = new SmsDto();
            Map<String, Object> data = new HashMap<>();
            WmsBasicWarehouseArea area = wmsBasicWarehouseAreas.stream().filter(o -> o.getId().equals(dto.getAreaId())).findFirst().get();
            data.put(MATERIALCODE, dto.getMaterialCode());
            data.put(WAREHOUSENAME, dto.getWarehouseName());
            data.put(AREANAME, area.getName());
            data.put(MATERIALQUANTITY, dto.getQuantity());
            data.put(AREAID, dto.getAreaId());
            if (ObjectUtil.isNotEmpty(area.getMaxCapacity())) {
                //仓库存在数量大于等于最大容量
                if (dto.getQuantity().compareTo(area.getMaxCapacity()) >= 0) {
                    //data.clear();
                    data.put(MAXQUANTITY, area.getMaxCapacity());
                    send(smsDto, maxTemplate, data);
                    i.incrementAndGet();
                } else {
                    //data.clear();
                    data.put(MAXQUANTITY, area.getMaxCapacity());
                    inactive(smsDto, maxTemplate, data);
                }
            }
            if (ObjectUtil.isNotEmpty(area.getWarningCapacity())) {
                //仓库库存数量小于等于预警容量
                if (dto.getQuantity().compareTo(area.getWarningCapacity()) <= 0) {
                    //data.clear();
                    data.put(SAFEQUANTITY, area.getWarningCapacity());
                    send(smsDto, safetyTemplate, data);
                    i.incrementAndGet();
                } else {
                    //data.clear();
                    data.put(SAFEQUANTITY, area.getWarningCapacity());
                    inactive(smsDto, safetyTemplate, data);
                }
            }
            //仓库库存数量小于等于最低容量
            if (dto.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
                //data.clear();
                data.put(MINQUANTITY, "0");
                send(smsDto, minTemplate, data);
                i.incrementAndGet();
            } else {
                //data.clear();
                data.put(MINQUANTITY, "0");
                inactive(smsDto, minTemplate, data);
            }
        }
        return i;
    }

    @Transactional(rollbackFor = Exception.class)
    public AtomicInteger countLocation() throws Exception {
        List<WmsBasicWarehouseAreaLocation> wmsBasicWarehouseAreaLocations = wmsBasicWarehouseAreaLocationMapper.selectList(new LambdaQueryWrapper<>());
        String maxTemplate = "location-max";
        String safetyTemplate = "location-safety";
        String minTemplate = "location-min";
        List<CountQuantityDTO> areaQuantity = wmsRepertoryMapper.countLocation();
        AtomicInteger i = new AtomicInteger(0);
        for (CountQuantityDTO dto : areaQuantity) {
            SmsDto smsDto = new SmsDto();
            Map<String, Object> data = new HashMap<>();
            WmsBasicWarehouseAreaLocation location = wmsBasicWarehouseAreaLocations.stream().filter(o -> o.getId().equals(dto.getLocationId())).findFirst().get();
            data.put(MATERIALCODE, dto.getMaterialCode());
            data.put(WAREHOUSENAME, dto.getWarehouseName());
            data.put(AREANAME, dto.getAreaName());
            data.put(LOCATIONNAME, location.getName());
            data.put(MATERIALQUANTITY, dto.getQuantity());
            data.put(LOCATIONID, dto.getLocationId());
            if (ObjectUtil.isNotEmpty(location.getMaxCapacity())) {
                //仓库存在数量大于等于最大容量
                if (dto.getQuantity().compareTo(location.getMaxCapacity()) >= 0) {
                    //data.clear();
                    data.put(MAXQUANTITY, location.getMaxCapacity());
                    send(smsDto, maxTemplate, data);
                    i.incrementAndGet();
                } else {
                    //data.clear();
                    data.put(MAXQUANTITY, location.getMaxCapacity());
                    inactive(smsDto, maxTemplate, data);
                }
            }
            if (ObjectUtil.isNotEmpty(location.getWarningCapacity())) {
                //仓库库存数量小于等于预警容量
                if (dto.getQuantity().compareTo(location.getWarningCapacity()) <= 0) {
                    //data.clear();
                    data.put(SAFEQUANTITY, location.getWarningCapacity());
                    send(smsDto, safetyTemplate, data);
                    i.incrementAndGet();
                } else {
                    //data.clear();
                    data.put(SAFEQUANTITY, location.getWarningCapacity());
                    inactive(smsDto, safetyTemplate, data);
                }
            }
            //仓库库存数量小于等于最低容量
            if (dto.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
                //data.clear();
                data.put(MINQUANTITY, 0);
                send(smsDto, minTemplate, data);
                i.incrementAndGet();
            } else {
                //data.clear();
                data.put(MINQUANTITY, 0);
                inactive(smsDto, minTemplate, data);
            }
        }
        return i;
    }

    //发预警消息
    private void send(SmsDto smsDto, String template, Map<String, Object> data) throws Exception {
        smsDto.setTemplateCode(template);
        smsDto.setData(data);
        alertService.send(smsDto);
        int i = count.incrementAndGet();
        log.info("发了第{}次：{}", i, smsDto);
    }

    //取消预警
    private void inactive(SmsDto smsDto, String template, Map<String, Object> data) throws Exception {
        smsDto.setTemplateCode(template);
        smsDto.setData(data);
        alertService.inActive(smsDto);
    }

}
